package widgets

import (
	"reflect"
	"strconv"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/data/binding"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/widget"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/tidwall/gjson"
	"github.com/y2h/fyne_poem/dbb"
	"github.com/y2h/fyne_poem/util"
)

// ALTER TABLE table_name ADD column_name datatype
// ALTER TABLE table_name DROP COLUMN column_name
// ALTER TABLE table_name ALTER COLUMN column_name datatype
// ALTER TABLE database_name.table_name RENAME TO new_table_name;

// 数据表所有列名数组
var Bdcols binding.StringList

// 使用github.com/tidwall/gjson获取结构体gdb.TableField的所有字段及其值
func field(db gdb.DB, tbl string,
	msg *widget.Label, w fyne.Window) fyne.CanvasObject {
	fds, cols := dbb.SqliteTblColsGF(db, tbl)
	if len(cols) == 0 {
		return widget.NewLabel("no data")
	}
	g0 := gjson.Parse(gconv.String(fds[cols[0]]))
	header := []string{}
	// 表的列结构体类型
	g0.ForEach(func(key, value gjson.Result) bool {
		header = append(header, key.String())
		return true
	})
	// 表的列结构体字段数量
	numfd := len(header)
	// 表头,表的列结构体字段
	head := container.NewGridWithColumns(numfd)
	g0.ForEach(func(key, value gjson.Result) bool {
		head.Add(widget.NewLabel(key.String()))
		return true
	})

	lst := widget.NewList(func() int {
		return len(cols)
	}, func() fyne.CanvasObject {
		hb := container.NewGridWithColumns(numfd)
		for i := 0; i < numfd; i++ {
			hb.Add(widget.NewLabel("field"))
		}
		return hb
	}, func(lii widget.ListItemID, co fyne.CanvasObject) {
		hb := co.(*fyne.Container)
		gi := gjson.Parse(gconv.String(fds[cols[lii]]))
		i := 0
		gi.ForEach(func(key, value gjson.Result) bool {
			lbli := hb.Objects[i].(*widget.Label)
			lbli.SetText(value.String())
			i++
			return true
		})
	})

	right := Frmtblfield(tbl)
	lbl := widget.NewLabel("")
	colNamesel := ""
	selectedID := 0
	lst.OnSelected = func(id widget.ListItemID) {
		selectedID = id
		colNamesel = cols[id]
		lbl.SetText(gconv.String(fds[cols[id]]))

		right.Items[0].Widget.(*widget.Entry).
			SetText(gconv.String(fds[cols[id]].Index))
		right.Items[1].Widget.(*widget.Select).
			SetSelected(gstr.ToUpper(fds[cols[id]].Type))
		right.Items[2].Widget.(*widget.Check).
			SetChecked(fds[cols[id]].Null)
		right.Items[3].Widget.(*widget.Entry).
			SetText(fds[cols[id]].Key)
		right.Items[4].Widget.(*widget.Entry).
			SetText(gconv.String(fds[cols[id]].Default))
		right.Items[5].Widget.(*widget.Entry).
			SetText(fds[cols[id]].Extra)
		right.Items[6].Widget.(*widget.Entry).
			SetText(fds[cols[id]].Comment)
		right.Items[7].Widget.(*widget.Entry).
			SetText(fds[cols[id]].Name)
		msg.SetText(colNamesel)
	}
	btnAddCol := widget.NewButton("AddCol", func() {
		w := fyne.CurrentApp().NewWindow("Add column")
		w.Resize(fyne.NewSize(500, 500))
		colName := widget.NewEntry()
		colType := widget.NewSelect(util.DATATYPE, nil)
		btnOk := widget.NewButton("Ok", func() {
			sql := "ALTER TABLE " + tbl + " ADD " + colName.Text + " " + colType.Selected
			_, err := db.Exec(db.GetCtx(), sql)
			if err != nil {
				msg.SetText(err.Error())
				return
			}
			msg.SetText("add column success")

			// 手动新增
			// fds[colName.Text] = &gdb.TableField{
			// 	Index: len(cols),
			// 	Name:  colName.Text,
			// 	Type:  colType.Selected,
			// 	Null:  true,
			// }
			// cols = append(cols, colName.Text)

			// 使用*sql.DB数据库原生方法可得到正确结果
			fds, cols = dbb.SqliteTblColsGF(db, tbl)

			// fds, cols = SqliteTblColsGF(db, tbl)
			lst.Select(len(cols) - 1)
			// lst.Refresh()
			// kcol := util.TblCol(tbl, "字段") + "(" + gconv.String(len(cols)) + ")"
			// util.Data[kcol] = append(util.Data[kcol], util.TblCol(tbl, colName.Text))
			util.Data[tbl] = append(util.Data[tbl], util.TblCol(tbl, colName.Text))
			rs, _ := db.Model(tbl).OrderDesc(cols[0]).Limit(20).All()
			RefreshListResult(lstData, db, tbl, rs, msg, w)
			CtnHeader.Objects[0] = Header(cols, 2)
			Bdcols.Set(cols)
		})
		cc := container.NewVBox(colName, colType, btnOk)
		w.SetContent(cc)
		w.Show()
	})
	btnDelete := widget.NewButton("DeleteCol", func() {
		dialog.ShowConfirm("Delete Column", "Delete column "+colNamesel,
			func(b bool) {
				if b {
					sql := "ALTER TABLE " + tbl + " DROP " + colNamesel
					_, err := db.Exec(db.GetCtx(), sql)
					if err != nil {
						msg.SetText(err.Error())
						return
					}
					msg.SetText("drop column " + colNamesel + " success")
					// 手动删除
					// cols = Deletes(cols, colNamesel)
					// var fdsn = make(map[string]*gdb.TableField)
					// for i, k := range cols {
					// 	fdsn[k] = fds[k]
					// 	fdsn[k].Index = i
					// }
					// fds=fdsn

					fds, cols = dbb.SqliteTblColsGF(db, tbl)
					// fds, cols = dbb.SqliteTblColsGF1(db, tbl)
					util.Data[tbl] = util.Deletes(util.Data[tbl], util.TblCol(tbl, colNamesel))
					// kcol := util.TblCol(tbl, "字段") + "(" + gconv.String(len(cols)) + ")"
					// util.Data[kcol] = util.Deletes(util.Data[kcol], util.TblCol(tbl, colNamesel))

					lst.Select(selectedID - 1)

					// _, tblCols := dbb.SqliteTblColsGF(db, tbl)
					// 					rs, _ := db.Model(tbl).OrderDesc(tblCols[0]).Limit(20).All()
					// 					RefreshListResult(lstData, db, tbl, rs, msg, w)

					CtnHeader.Objects[0] = Header(cols, 2)
					Bdcols.Set(cols)
				}
			}, w)
	})
	top := container.NewHBox(btnAddCol, btnDelete)
	left := container.NewBorder(top, nil, nil, nil,
		container.NewBorder(head, lbl, nil, nil, lst))
	cc := container.NewHSplit(left, right)
	cc.Offset = 0.7
	return cc
}

// 使用反射获取结构体gdb.TableField的所有字段及其值
func field2(db gdb.DB, tbl string) fyne.CanvasObject {
	// fds, _ := db.TableFields(newDb.GetCtx(), tbl)
	// 表的列名数组
	fds, cols := dbb.SqliteTblColsGF(db, tbl)
	// 表的列结构体类型
	ty0 := reflect.TypeOf(*fds[cols[0]])
	// 表的列结构体字段数量
	numfd := ty0.NumField()
	// 表头,表的列结构体字段
	head := container.NewGridWithColumns(numfd)
	for i := 0; i < numfd; i++ {
		head.Add(widget.NewLabel(ty0.Field(i).Name))
	}

	lst := widget.NewList(func() int {
		return len(cols)
	}, func() fyne.CanvasObject {
		hb := container.NewGridWithColumns(numfd)
		for i := 0; i < numfd; i++ {
			hb.Add(widget.NewLabel("field"))
		}
		return hb
	}, func(lii widget.ListItemID, co fyne.CanvasObject) {
		hb := co.(*fyne.Container)
		vai := reflect.ValueOf(*fds[cols[lii]])
		for i := 0; i < numfd; i++ {
			lbli := hb.Objects[i].(*widget.Label)
			lbli.SetText(gconv.String(vai.Field(i).Interface()))
		}
	})
	lbl := widget.NewLabel("")
	lst.OnSelected = func(id widget.ListItemID) {
		lbl.SetText(gconv.String(fds[cols[id]]))
	}
	return container.NewBorder(head, lbl, nil, nil, lst)
}

// 获取结构体gdb.TableField的所有字段及其值
func field1(db gdb.DB, tbl string) fyne.CanvasObject {
	// fds, _ := db.TableFields(newDb.GetCtx(), tbl)
	// cols := GetFields(db, tbl)
	fds, cols := dbb.SqliteTblColsGF(db, tbl)
	head := container.NewGridWithColumns(8)
	head.Add(widget.NewLabel("Name"))
	head.Add(widget.NewLabel("Index"))
	head.Add(widget.NewLabel("Type"))
	head.Add(widget.NewLabel("Null"))
	head.Add(widget.NewLabel("Key"))
	head.Add(widget.NewLabel("Default"))
	head.Add(widget.NewLabel("Extra"))
	head.Add(widget.NewLabel("Comment"))
	lst := widget.NewList(func() int {
		return len(cols)
	}, func() fyne.CanvasObject {
		hb := container.NewGridWithColumns(8)
		for i := 0; i < 8; i++ {
			hb.Add(widget.NewLabel("field"))
		}
		return hb
	}, func(lii widget.ListItemID, co fyne.CanvasObject) {
		hb := co.(*fyne.Container)
		lbl0 := hb.Objects[0].(*widget.Label)
		lbl0.SetText(fds[cols[lii]].Name)
		lbl1 := hb.Objects[1].(*widget.Label)
		lbl1.SetText(strconv.Itoa(fds[cols[lii]].Index))
		lbl2 := hb.Objects[2].(*widget.Label)
		lbl2.SetText(fds[cols[lii]].Type)
		lbl3 := hb.Objects[3].(*widget.Label)
		lbl3.SetText(gconv.String(fds[cols[lii]].Null))
		lbl4 := hb.Objects[4].(*widget.Label)
		lbl4.SetText(fds[cols[lii]].Key)
		lbl5 := hb.Objects[5].(*widget.Label)
		lbl5.SetText(gconv.String(fds[cols[lii]].Default))
		lbl6 := hb.Objects[6].(*widget.Label)
		lbl6.SetText(fds[cols[lii]].Extra)
		lbl7 := hb.Objects[7].(*widget.Label)
		lbl7.SetText(fds[cols[lii]].Comment)
	})
	lbl := widget.NewLabel("")
	lst.OnSelected = func(id widget.ListItemID) {
		lbl.SetText(gconv.String(fds[cols[id]]))
	}
	return container.NewBorder(head, lbl, nil, nil, lst)
}
